#include "SQLColumnDefinition.h"

#include "SQLAssignItem.h"

#include "../../SQLUtils.h"
#include "../../../utils/instanceof.h"
#include "../../visitor/SQLASTVisitor.h"
#include "../../../utils/listTran.h"

Identity::Identity()
{
}

int Identity::getSeed()
{
  return seed;
}

void Identity::setSeed(int seed)
{
  this->seed = seed;
}

int Identity::getIncrement()
{
  return increment;
}

void Identity::setIncrement(int increment)
{
  this->increment = increment;
}

BOOL_ptr Identity::isCycle()
{
  return cycle;
}

void Identity::setCycle(BOOL_ptr cycle)
{
  this->cycle = cycle;
}

int Identity::getMinValue()
{
  return minValue;
}

void Identity::setMinValue(int minValue)
{
  this->minValue = minValue;
}

int Identity::getMaxValue()
{
  return maxValue;
}

void Identity::setMaxValue(int maxValue)
{
  this->maxValue = maxValue;
}

BOOL_ptr Identity::isNotForReplication()
{
  return notForReplication;
}

void Identity::setNotForReplication(BOOL_ptr notForReplication)
{
  this->notForReplication = notForReplication;
}

void Identity::accept0(SQLASTVisitor_ptr visitor)
{
  visitor->visit(SharedObject(Identity));
  visitor->endVisit(SharedObject(Identity));
}

SQLObject_ptr Identity::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<Identity>(new Identity());
  std::shared_ptr<Identity> x = std::dynamic_pointer_cast<Identity>(clone_tmp);
  // Identity *x = new Identity();
  x->seed = seed;
  x->increment = increment;
  x->cycle = cycle;
  x->minValue = minValue;
  x->maxValue = maxValue;
  x->notForReplication = notForReplication;
  return x;
}

SQLCharExpr_ptr SQLColumnDefinition::getIndexComment()
{
  return indexComment;
}

void SQLColumnDefinition::setIndexComment(SQLCharExpr_ptr indexComment)
{
  this->indexComment = indexComment;
}

SQLCharExpr_ptr SQLColumnDefinition::getBitmap()
{
  return bitmap;
}

void SQLColumnDefinition::setBitmap(SQLCharExpr_ptr bitmap)
{
  this->bitmap = bitmap;
}

SQLCharExpr_ptr SQLColumnDefinition::getAggType()
{
  return aggType;
}

void SQLColumnDefinition::setAggType(SQLCharExpr_ptr aggType)
{
  this->aggType = aggType;
}

SQLColumnDefinition::SQLColumnDefinition()
{
  constraints = std::make_shared<std::list<std::shared_ptr<SQLColumnConstraint>>>();
  mappedBy = std::make_shared<std::list<SQLAssignItem_ptr>>();
  colProperties = std::make_shared<std::list<SQLAssignItem_ptr>>();
}

Identity_ptr SQLColumnDefinition::getIdentity()
{
  return identity;
}

// for sqlserver
void SQLColumnDefinition::setIdentity(Identity_ptr identity)
{
  if (identity != NULL)
  {
    identity->setParent(SharedObject(SQLColumnDefinition));
  }
  this->identity = identity;
}

BOOL_ptr SQLColumnDefinition::getEnable()
{
  return enable;
}

void SQLColumnDefinition::setEnable(BOOL_ptr enable)
{
  this->enable = enable;
}

BOOL_ptr SQLColumnDefinition::getValidate()
{
  return validate;
}

void SQLColumnDefinition::setValidate(BOOL_ptr validate)
{
  this->validate = validate;
}

BOOL_ptr SQLColumnDefinition::getRely()
{
  return rely;
}

void SQLColumnDefinition::setRely(BOOL_ptr rely)
{
  this->rely = rely;
}

SQLName_ptr SQLColumnDefinition::getName()
{
  return name;
}

string_ptr SQLColumnDefinition::getColumnName()
{
  if (name == NULL)
  {
    return NULL;
  }

  return name->getSimpleName();
}

long SQLColumnDefinition::nameHashCode64()
{
  if (name == NULL)
  {
    return 0;
  }

  return name->hashCode64();
}

string_ptr SQLColumnDefinition::getNameAsString()
{
  if (name == NULL)
  {
    return NULL;
  }

  return name->toString();
}

void SQLColumnDefinition::setName(SQLName_ptr name)
{
  this->name = name;
}

void SQLColumnDefinition::setName(string_ptr name)
{
  this->setName(SQLIdentifierExpr_ptr(new SQLIdentifierExpr(name)));
}

SQLDataType_ptr SQLColumnDefinition::getDataType()
{
  return dataType;
}

int SQLColumnDefinition::jdbcType()
{
  if (dataType == NULL)
  {
    return 1111;
  }

  return dataType->jdbcType();
}

void SQLColumnDefinition::setDataType(SQLDataType_ptr dataType)
{
  if (dataType != NULL)
  {
    dataType->setParent(SharedObject(SQLColumnDefinition));
  }
  this->dataType = dataType;
}

SQLExpr_ptr SQLColumnDefinition::getDefaultExpr()
{
  return defaultExpr;
}

void SQLColumnDefinition::setDefaultExpr(SQLExpr_ptr defaultExpr)
{
  if (defaultExpr != NULL)
  {
    defaultExpr->setParent(SharedObject(SQLColumnDefinition));
  }
  this->defaultExpr = defaultExpr;
}

SQLColumnConstraint_list_ptr SQLColumnDefinition::getConstraints()
{
  return constraints;
}

// BOOL_ptr isPrimaryKey() {
//     for (SQLColumnConstraint constraint : constraints) {
//         if (constraint instanceof SQLColumnPrimaryKey) {
//             return BOOL::TRUE;
//         }
//     }

//     if (parent instanceof SQLCreateTableStatement) {
//         return ((SQLCreateTableStatement) parent)
//                 .isPrimaryColumn(
//                         nameHashCode64());
//     }

//     return BOOL::FALSE;
// }

// BOOL_ptr isOnlyPrimaryKey() {
//     for (SQLColumnConstraint constraint : constraints) {
//         if (constraint instanceof SQLColumnPrimaryKey) {
//             return BOOL::TRUE;
//         }
//     }

//     if (parent instanceof SQLCreateTableStatement) {
//         return ((SQLCreateTableStatement) parent)
//                 .isPrimaryColumn(
//                         nameHashCode64());
//     }

//     return BOOL::FALSE;
// }

// BOOL_ptr isPartitionBy() {
//     if (!(parent instanceof SQLCreateTableStatement)) {
//         return BOOL::FALSE;
//     }

//     SQLCreateTableStatement* stmt = (SQLCreateTableStatement) parent;
//     SQLPartitionBy partitioning = stmt.getPartitioning();
//     if (partitioning == NULL) {
//         return BOOL::FALSE;
//     }

//     if (name == NULL) {
//         return BOOL::FALSE;
//     }

//     return partitioning.isPartitionByColumn(
//             nameHashCode64());
// }

void SQLColumnDefinition::addConstraint(std::shared_ptr<SQLColumnConstraint> constraint)
{
  if (constraint != NULL)
  {
    constraint->setParent(SharedObject(SQLColumnDefinition));
  }
  this->constraints->push_back(constraint);
}

void SQLColumnDefinition::accept0(SQLASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(SQLColumnDefinition)))
  {
    this->acceptChild(visitor, name);
    this->acceptChild(visitor, std::dynamic_pointer_cast<SQLObject>(dataType));
    this->acceptChild(visitor, defaultExpr);
    SQLObject_list_ptr tmp = ListTran::tran_class<SQLColumnConstraint, SQLObject>(constraints);
    this->acceptChild(visitor, tmp);
  }
  visitor->endVisit(SharedObject(SQLColumnDefinition));
}

SQLExpr_ptr SQLColumnDefinition::getComment()
{
  return comment;
}

void SQLColumnDefinition::setComment(string_ptr comment)
{
  SQLCharExpr_ptr expr;
  if (comment->empty())
  {
    expr = NULL;
  }
  else
  {
    expr = SQLCharExpr_ptr(new SQLCharExpr(comment));
  }
  this->setComment(expr);
}

void SQLColumnDefinition::setComment(SQLExpr_ptr comment)
{
  if (comment != NULL)
  {
    comment->setParent(SharedObject(SQLColumnDefinition));
  }
  this->comment = comment;
}

BOOL_ptr SQLColumnDefinition::isVirtual()
{
  return virtual_;
}

void SQLColumnDefinition::setVirtual(BOOL_ptr virtual_)
{
  this->virtual_ = virtual_;
}

BOOL_ptr SQLColumnDefinition::isStored()
{
  return stored;
}

void SQLColumnDefinition::setStored(BOOL_ptr stored)
{
  this->stored = stored;
}

SQLExpr_ptr SQLColumnDefinition::getCharsetExpr()
{
  return charsetExpr;
}

void SQLColumnDefinition::setCharsetExpr(SQLExpr_ptr charsetExpr)
{
  if (charsetExpr != NULL)
  {
    charsetExpr->setParent(SharedObject(SQLColumnDefinition));
  }
  this->charsetExpr = charsetExpr;
}

SQLExpr_ptr SQLColumnDefinition::getCollateExpr()
{
  return collateExpr;
}

void SQLColumnDefinition::setCollateExpr(SQLExpr_ptr x)
{
  if (charsetExpr != NULL)
  {
    charsetExpr->setParent(SharedObject(SQLColumnDefinition));
  }
  this->collateExpr = x;
}

SQLExpr_ptr SQLColumnDefinition::getAsExpr()
{
  return asExpr;
}

void SQLColumnDefinition::setAsExpr(SQLExpr_ptr asExpr)
{
  if (charsetExpr != NULL)
  {
    charsetExpr->setParent(SharedObject(SQLColumnDefinition));
  }
  this->asExpr = asExpr;
}

BOOL_ptr SQLColumnDefinition::isAutoIncrement()
{
  return autoIncrement;
}

void SQLColumnDefinition::setAutoIncrement(BOOL_ptr autoIncrement)
{
  this->autoIncrement = autoIncrement;
}

SQLExpr_ptr SQLColumnDefinition::getOnUpdate()
{
  return onUpdate;
}

void SQLColumnDefinition::setOnUpdate(SQLExpr_ptr onUpdate)
{
  this->onUpdate = onUpdate;
}

SQLExpr_ptr SQLColumnDefinition::getFormat()
{
  return format;
}

void SQLColumnDefinition::setFormat(SQLExpr_ptr format)
{
  this->format = format;
}

SQLExpr_ptr SQLColumnDefinition::getStorage()
{
  return storage;
}

void SQLColumnDefinition::setStorage(SQLExpr_ptr storage)
{
  this->storage = storage;
}

BOOL_ptr SQLColumnDefinition::replace(SQLExpr_ptr expr, SQLExpr_ptr target)
{
  if (defaultExpr == expr)
  {
    setDefaultExpr(target);
    return BOOL::TRUE;
  }

  if (name == expr)
  {
    setName(std::dynamic_pointer_cast<SQLName>(target));
    return BOOL::TRUE;
  }

  if (comment == expr)
  {
    setComment(target);
    return BOOL::TRUE;
  }

  return BOOL::FALSE;
}

void SQLColumnDefinition::setUnitCount(SQLExpr_ptr unitCount)
{
  if (unitCount != NULL)
  {
    unitCount->setParent(SharedObject(SQLColumnDefinition));
  }
  this->unitCount = unitCount;
}

// string_ptr  computeAlias() {
//     string_ptr  alias = NULL;

//     if (name instanceof SQLIdentifierExpr) {
//         alias = ((SQLIdentifierExpr) name).getName();
//     } else if (name instanceof SQLPropertyExpr) {
//         alias = ((SQLPropertyExpr) name).getName();
//     }

//     return SQLUtils.normalize(alias);
// }

SQLObject_ptr SQLColumnDefinition::clone()
{
  SQLObject_ptr clone_tmp = SQLColumnDefinition_ptr(new SQLColumnDefinition());
  SQLColumnDefinition_ptr x = std::dynamic_pointer_cast<SQLColumnDefinition>(clone_tmp);
  // SQLColumnDefinition *x = new SQLColumnDefinition();
  x->setDbType(dbType);

  if (name != NULL)
  {
    x->setName(std::dynamic_pointer_cast<SQLName>(name->clone()));
  }

  if (dataType != NULL)
  {
    x->setDataType(std::dynamic_pointer_cast<SQLDataType>(dataType->clone()));
  }

  if (defaultExpr != NULL)
  {
    x->setDefaultExpr(std::dynamic_pointer_cast<SQLExpr>(defaultExpr->clone()));
  }

  for (std::shared_ptr<SQLColumnConstraint> item : *constraints)
  {
    std::shared_ptr<SQLColumnConstraint> itemCloned = std::dynamic_pointer_cast<SQLColumnConstraint>(item->clone());
    itemCloned->setParent(x);
    x->constraints->push_back(itemCloned);
  }

  if (comment != NULL)
  {
    x->setComment(std::dynamic_pointer_cast<SQLExpr>(comment->clone()));
  }

  x->enable = enable;
  x->validate = validate;
  x->rely = rely;

  x->autoIncrement = autoIncrement;

  if (onUpdate != NULL)
  {
    x->setOnUpdate(std::dynamic_pointer_cast<SQLExpr>(onUpdate->clone()));
  }

  if (format != NULL)
  {
    x->setFormat(std::dynamic_pointer_cast<SQLExpr>(format->clone()));
  }

  if (storage != NULL)
  {
    x->setStorage(std::dynamic_pointer_cast<SQLExpr>(storage->clone()));
  }

  if (charsetExpr != NULL)
  {
    x->setCharsetExpr(std::dynamic_pointer_cast<SQLExpr>(charsetExpr->clone()));
  }

  if (collateExpr != NULL)
  {
    x->setCollateExpr(std::dynamic_pointer_cast<SQLExpr>(collateExpr->clone()));
  }

  if (asExpr != NULL)
  {
    x->setAsExpr(std::dynamic_pointer_cast<SQLExpr>(asExpr->clone()));
  }

  x->stored = stored;
  x->virtual_ = virtual_;

  if (identity != NULL)
  {
    x->setIdentity(std::dynamic_pointer_cast<Identity>(identity->clone()));
  }

  if (delimiter != NULL)
  {
    x->setDelimiter(std::dynamic_pointer_cast<SQLExpr>(delimiter->clone()));
  }

  if (valueType != NULL)
  {
    x->setValueType(std::dynamic_pointer_cast<SQLExpr>(valueType->clone()));
  }

  if (nlpTokenizer != NULL)
  {
    x->setNplTokenizer(std::dynamic_pointer_cast<SQLExpr>(nlpTokenizer->clone()));
  }

  x->preSort = preSort;
  x->preSortOrder = preSortOrder;

  if (jsonIndexAttrsExpr != NULL)
  {
    x->setJsonIndexAttrsExpr(std::dynamic_pointer_cast<SQLExpr>(jsonIndexAttrsExpr->clone()));
  }

  if (annIndex != NULL)
  {
    x->setAnnIndex(std::dynamic_pointer_cast<SQLAnnIndex>(annIndex->clone()));
  }

  if (!mappedBy->empty())
  {
    for (SQLAssignItem_ptr item : *mappedBy)
    {
      SQLAssignItem_ptr item2 = std::dynamic_pointer_cast<SQLAssignItem>(item->clone());
      item2->setParent(SharedObject(SQLColumnDefinition));
      if (x->mappedBy == nullptr)
      {
        x->mappedBy = std::shared_ptr<std::__cxx11::list<SQLAssignItem_ptr>>();
      }
      x->mappedBy->push_back(item2);
    }
  }

  if (!colProperties->empty())
  {
    for (SQLAssignItem_ptr item : *colProperties)
    {
      SQLAssignItem_ptr item2 = std::dynamic_pointer_cast<SQLAssignItem>(item->clone());
      item2->setParent(SharedObject(SQLColumnDefinition));
      if (x->colProperties == nullptr)
      {
        x->colProperties = std::shared_ptr<std::__cxx11::list<SQLAssignItem_ptr>>();
      }
      x->colProperties->push_back(item2);
    }
  }

  return x;
}

DbType_ptr SQLColumnDefinition::getDbType()
{
  return dbType;
}

void SQLColumnDefinition::setDbType(DbType_ptr dbType)
{
  this->dbType = dbType;
}

void SQLColumnDefinition::simplify()
{
  enable = NULL;
  validate = NULL;
  rely = NULL;

  if (instanceof <SQLName, SQLIdentifierExpr>(this->name))
  {
    SQLIdentifierExpr_ptr identExpr = std::dynamic_pointer_cast<SQLIdentifierExpr>(this->name);
    string_ptr columnName = identExpr->getName();
    string_ptr normalized = SQLUtils::normalize(columnName, dbType);
    if (*normalized != *columnName)
    {
      this->setName(normalized);
    }
  }
}

BOOL_ptr SQLColumnDefinition::containsNotNullConstaint()
{
  // for (SQLColumnConstraint *constraint : this->constraints)
  // {
  //   if (instanceof <SQLColumnConstraint, SQLNotNullConstraint>(constraint))
  //   {
  //     return BOOL::TRUE;
  //   }
  // }

  return BOOL::FALSE;
}

SQLExpr_ptr SQLColumnDefinition::getGeneratedAlawsAs()
{
  return generatedAlawsAs;
}

void SQLColumnDefinition::setGeneratedAlawsAs(SQLExpr_ptr x)
{
  if (x != NULL)
  {
    x->setParent(SharedObject(SQLColumnDefinition));
  }
  this->generatedAlawsAs = x;
}

BOOL_ptr SQLColumnDefinition::isVisible()
{
  return visible;
}

void SQLColumnDefinition::setVisible(BOOL_ptr visible)
{
  this->visible = visible;
}

SQLExpr_ptr SQLColumnDefinition::getDelimiter()
{
  return delimiter;
}

BOOL_ptr SQLColumnDefinition::isDisableIndex()
{
  return disableIndex;
}

void SQLColumnDefinition::setDisableIndex(BOOL_ptr disableIndex)
{
  this->disableIndex = disableIndex;
}

void SQLColumnDefinition::setDelimiter(SQLExpr_ptr x)
{
  if (x != NULL)
  {
    x->setParent(SharedObject(SQLColumnDefinition));
  }
  this->delimiter = x;
}

SQLExpr_ptr SQLColumnDefinition::getDelimiterTokenizer()
{
  return delimiterTokenizer;
}

void SQLColumnDefinition::setDelimiterTokenizer(SQLExpr_ptr delimiterTokenizer)
{
  this->delimiterTokenizer = delimiterTokenizer;
}

SQLExpr_ptr SQLColumnDefinition::getNlpTokenizer()
{
  return nlpTokenizer;
}

void SQLColumnDefinition::setNlpTokenizer(SQLExpr_ptr nlpTokenizer)
{
  this->nlpTokenizer = nlpTokenizer;
}

SQLExpr_ptr SQLColumnDefinition::getValueType()
{
  return valueType;
}

void SQLColumnDefinition::setValueType(SQLExpr_ptr x)
{
  if (x != NULL)
  {
    x->setParent(SharedObject(SQLColumnDefinition));
  }
  this->valueType = x;
}

BOOL_ptr SQLColumnDefinition::isPreSort()
{
  return preSort;
}

void SQLColumnDefinition::setPreSort(BOOL_ptr preSort)
{
  this->preSort = preSort;
}

int SQLColumnDefinition::getPreSortOrder()
{
  return preSortOrder;
}

void SQLColumnDefinition::setPreSortOrder(int preSortOrder)
{
  this->preSortOrder = preSortOrder;
}

SQLExpr_ptr SQLColumnDefinition::getJsonIndexAttrsExpr()
{
  return jsonIndexAttrsExpr;
}

void SQLColumnDefinition::setJsonIndexAttrsExpr(SQLExpr_ptr jsonIndexAttrsExpr)
{
  this->jsonIndexAttrsExpr = jsonIndexAttrsExpr;
}

SQLAnnIndex_ptr SQLColumnDefinition::getAnnIndex()
{
  return annIndex;
}

void SQLColumnDefinition::setAnnIndex(SQLAnnIndex_ptr x)
{
  if (x != NULL)
  {
    x->setParent(SharedObject(SQLColumnDefinition));
  }
  this->annIndex = x;
}

AutoIncrementType_ptr SQLColumnDefinition::getSequenceType()
{
  return sequenceType;
}

void SQLColumnDefinition::setSequenceType(AutoIncrementType_ptr sequenceType)
{
  this->sequenceType = sequenceType;
}

string_ptr SQLColumnDefinition::toString()
{
  string_ptr tmp = SQLUtils::toSQLString(std::dynamic_pointer_cast<SQLObject>(SharedObject(SQLColumnDefinition)), dbType);
  return (tmp);
}

SQLExpr_ptr SQLColumnDefinition::getUnitCount()
{
  return unitCount;
}

SQLExpr_ptr SQLColumnDefinition::getUnitIndex()
{
  return unitIndex;
}

void SQLColumnDefinition::setUnitIndex(SQLExpr_ptr unitIndex)
{
  if (unitIndex != NULL)
  {
    unitIndex->setParent(SharedObject(SQLColumnDefinition));
  }
  this->unitIndex = unitIndex;
}

SQLExpr_ptr SQLColumnDefinition::getNplTokenizer()
{
  return nlpTokenizer;
}

void SQLColumnDefinition::setNplTokenizer(SQLExpr_ptr x)
{
  if (x != NULL)
  {
    x->setParent(SharedObject(SQLColumnDefinition));
  }
  this->nlpTokenizer = x;
}

SQLExpr_ptr SQLColumnDefinition::getStep()
{
  return step;
}

void SQLColumnDefinition::setStep(SQLExpr_ptr step)
{
  if (step != NULL)
  {
    step->setParent(SharedObject(SQLColumnDefinition));
  }
  this->step = step;
}

SQLAssignItem_list_ptr SQLColumnDefinition::getMappedBy()
{
  if (mappedBy == NULL)
  {
    mappedBy = std::shared_ptr<std::__cxx11::list<SQLAssignItem_ptr>>();
  }
  return mappedBy;
}

SQLAssignItem_list_ptr SQLColumnDefinition::getMappedByDirect()
{
  return mappedBy;
}

SQLAssignItem_list_ptr SQLColumnDefinition::getColProperties()
{
  // if (colProperties == NULL) {
  //     colProperties = new ArrayList<SQLAssignItem*>();
  // }
  return colProperties;
}

SQLCharExpr_ptr SQLColumnDefinition::getEncode()
{
  return encode;
}

void SQLColumnDefinition::setEncode(SQLCharExpr_ptr encode)
{
  this->encode = encode;
}

SQLCharExpr_ptr SQLColumnDefinition::getCompression()
{
  return compression;
}

void SQLColumnDefinition::setCompression(SQLCharExpr_ptr compression)
{
  this->compression = compression;
}

SQLAssignItem_list_ptr SQLColumnDefinition::getColPropertiesDirect()
{
  return colProperties;
}
